home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / Mac OS USB DDK / Examples / CompositeClassDriver / CompositeClassDriver.c next >
Encoding:
C/C++ Source or Header  |  1999-02-10  |  9.5 KB  |  257 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CompositeClassDriver.c
  3.  
  4.     Contains:    Core functionality to Composite Class Driver
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "CompositeClassDriver.h"
  19. extern    usbCompositePBStruct myCompositePBRecord;
  20.  
  21.  
  22. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  23. {
  24.     paramblock->usbReference = theDeviceRef;
  25.     paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  26.     paramblock->pbLength = sizeof(usbCompositePBStruct);
  27.     paramblock->pbVersion = kUSBCurrentPBVersion;
  28.     paramblock->usb.cntl.WIndex = 0;             
  29.     paramblock->usbBuffer = nil;        
  30.     paramblock->usbStatus = kUSBNoErr;
  31.     paramblock->usbReqCount = 0;
  32.     paramblock->usbActCount = 0;
  33.     paramblock->usb.cntl.WValue = 0;
  34.     paramblock->usbFlags = 0;
  35. }
  36.  
  37.  
  38. Boolean immediateError(OSStatus err)
  39. {
  40.     return((err != kUSBPending) && (err != kUSBNoErr) );
  41. }
  42.  
  43. void CompositeDeviceInitiateTransaction(USBPB *pb)
  44. {
  45. register usbCompositePBStruct *pCompositePB;
  46. OSStatus myErr;
  47.  
  48.     pCompositePB = (usbCompositePBStruct *)(pb);
  49.     pCompositePB->transDepth++;
  50.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  51.     {
  52.     
  53.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Illegal Transaction Depth", pCompositePB->pb.usbRefcon);
  54.     }
  55.     
  56.     if (pCompositePB->driverRemovalPending)
  57.     {
  58.         pCompositePB->pb.usbRefcon = kReturnFromDriver;
  59.         return;
  60.     }
  61.  
  62.     switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction)
  63.     {
  64.         case kGetFullConfiguration0:
  65.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  66.             pCompositePB->pb.usb.cntl.WIndex = 0;             /* First try configuration 0, if it doesn't succeed, then try config 1*/
  67.             
  68.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  69.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  70.             myErr = USBGetFullConfigurationDescriptor(pb);
  71.             if(immediateError(myErr))
  72.             {
  73.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetFullConfiguration (#0) - immediate error", myErr);
  74.             }
  75.             break;
  76.         
  77.         case kGetFullConfiguration1:
  78.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  79.             pCompositePB->pb.usb.cntl.WIndex = 1;             /* Try configuration 1 (some devices seem to expect config 0, others config 1 */
  80.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  81.             
  82.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  83.             myErr = USBGetFullConfigurationDescriptor(pb);
  84.             if(immediateError(myErr))
  85.             {
  86.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetFullConfiguration (#1) - immediate error", myErr);
  87.             }
  88.             break;
  89.         
  90.         case kSetConfig:
  91.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  92.             pCompositePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);
  93.             
  94.             pCompositePB->pb.usb.cntl.BRequest = kUSBRqSetConfig;
  95.             pCompositePB->pb.usb.cntl.WValue = pCompositePB->pFullConfigDescriptor->configValue;         /* Use configuration ID value from descriptor */
  96.             
  97.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  98.             
  99.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  100.             myErr = USBDeviceRequest(pb);
  101.             if(immediateError(myErr))
  102.             {
  103.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kSetConfig - immediate error", myErr);
  104.             }
  105.             break;
  106.             
  107.         case kNewInterfaceRef:
  108.             InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  109.             // Note: pCompositePB->usb.cntl.WIndex will be set to zero by InitParamBlock
  110.             // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef
  111.             pCompositePB->pb.usb.cntl.WIndex = pCompositePB->interfaceIndex;
  112.             pCompositePB->pb.usbRefcon |= kCompletionPending;
  113.             pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  114.  
  115.             myErr = USBNewInterfaceRef(pb);
  116.             if(immediateError(myErr))
  117.             {
  118.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": kNewInterfaceRef - immediate error", myErr);
  119.             }
  120.             break;
  121.             
  122.         default:
  123.             USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon);
  124.             pCompositePB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  125.             break;
  126.     }
  127.     
  128. // At this point the control is returned to the system.  If a USB transaction
  129. // has been initiated, then it will call the Complete procs
  130. // (below) to handle the results of the transaction.
  131. }
  132.  
  133. void CompositeDeviceCompletionProc(USBPB *pb)
  134. {
  135. OSStatus myErr;
  136. register usbCompositePBStruct *pCompositePB;
  137. USBInterfaceDescriptorPtr pInterfaceDescriptor;
  138. UInt32 i;
  139.  
  140.     pCompositePB = (usbCompositePBStruct *)(pb);
  141.     pCompositePB->transDepth--;
  142.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  143.     {
  144.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Illegal Transaction Depth", pCompositePB->transDepth);
  145.     }
  146.     
  147.     if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending))
  148.     {
  149.         USBExpertStatus(pCompositePB->pb.usbReference, kCompositeDriverName": Completion Error", pCompositePB->pb.usbStatus);
  150.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  151.         pCompositePB->pb.usbRefcon |= kRetryTransaction;
  152.         pCompositePB->retryCount--;
  153.         if (!pCompositePB->retryCount)
  154.         {
  155.             if (pCompositePB->pb.usbRefcon == kGetFullConfiguration1)
  156.             {
  157.                 pCompositePB->pb.usbRefcon = kGetFullConfiguration0;
  158.             }
  159.             else
  160.             {
  161.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": Too many retries", pCompositePB->pb.usbRefcon);
  162.                 pCompositePB->pb.usbRefcon = kReturnFromDriver;
  163.                 return;
  164.             }
  165.         }
  166.     }
  167.     else
  168.     {
  169.         pCompositePB->pb.usbRefcon &= ~kRetryTransaction;
  170.         pCompositePB->retryCount = kCompositeRetryCount;
  171.     }
  172.  
  173.     if (pCompositePB->pb.usbRefcon & kCompletionPending)             
  174.     {                                                
  175.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  176.         switch(pCompositePB->pb.usbRefcon)
  177.         {
  178.             case kGetFullConfiguration0:
  179.             case kGetFullConfiguration1:
  180. //                DebugStr("\pCheck power");
  181.                 pCompositePB->pFullConfigDescriptor = pCompositePB->pb.usbBuffer;
  182.                 if (pCompositePB->pFullConfigDescriptor == nil)
  183.                 {
  184.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName": USBGetFullConfiguration - pointer is nil", pCompositePB->pb.usbRefcon);
  185.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  186.                     break;
  187.                 }
  188.                 
  189.                 BlockCopy(   (void *)pCompositePB->pFullConfigDescriptor, (void *)(&(pCompositePB->partialConfigDescriptor)), (Size)(sizeof(USBConfigurationDescriptor) )  );
  190.                 if (pCompositePB->pFullConfigDescriptor->maxPower <= pCompositePB->busPowerAvailable)
  191.                 {
  192.                     pCompositePB->pb.usbRefcon = kSetConfig;
  193.                 }
  194.                 else
  195.                 {
  196.                     USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, pCompositePB->pFullConfigDescriptor->maxPower);
  197.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBDevicePowerProblem, kCompositeDriverName" - Insufficient power for device", pCompositePB->pb.usbRefcon);
  198.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  199.                 }
  200.                 break;
  201.                 
  202.             case kSetConfig:            /* get all the interface descriptors and save them */
  203.                 for (i=0; i < pCompositePB->partialConfigDescriptor.numInterfaces; i++)
  204.                 {
  205.                     pCompositePB->interfaceRefArray[i] = 0;
  206.                     myErr = GetInterfaceDescriptor(pCompositePB->pFullConfigDescriptor, (UInt32)i, &pInterfaceDescriptor);
  207.                     if (kUSBNoErr == myErr)
  208.                     {
  209.                         BlockCopy((void *)pInterfaceDescriptor, (void *)(&(pCompositePB->interfaceDescriptors[i])), (Size)(pInterfaceDescriptor->length));
  210.                     }
  211.                     else                /* if GetInterfaceDescriptor returned an error, then set the length to zero (so we know later) */
  212.                     {
  213.                         pCompositePB->interfaceDescriptors[i].length = 0;
  214.                     }
  215.                 }
  216.                 pCompositePB->interfaceIndex = 0;
  217.                 pCompositePB->interfaceCount = pCompositePB->partialConfigDescriptor.numInterfaces;
  218.                 pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  219.                 break;
  220.                 
  221.             case kNewInterfaceRef:
  222.                 /* save the new interface ref for this interface */
  223.                 pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex] = pCompositePB->pb.usbReference;
  224.                 
  225.                 /* only install the interface driver if we had a valid interface descriptor */
  226.                 if (pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex].length != 0)
  227.                 {
  228.                     USBExpertInstallInterfaceDriver(pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex], &pCompositePB->deviceDescriptor, &pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex], pCompositePB->deviceRef, 0);
  229.                 }
  230.                 
  231.                 /* advance to the next interface */
  232.                 pCompositePB->interfaceIndex++;
  233.                 
  234.                 /* if there's more interfaces, then just keep cycling through kNewInterfaceRef */
  235.                 if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount)
  236.                 {
  237.                     pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  238.                 }
  239.                 else
  240.                 {
  241.                     pCompositePB->pb.usbRefcon = kReturnFromDriver;
  242.                 }
  243.                 break;
  244.             
  245.             default:
  246.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, kCompositeDriverName" - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon);
  247.                 pCompositePB->pb.usbRefcon = kReturnFromDriver;
  248.                 break;
  249.         }
  250.     }
  251.     if (!(pCompositePB->pb.usbRefcon & kReturnFromDriver) && (!pCompositePB->driverRemovalPending))
  252.         CompositeDeviceInitiateTransaction(pb);
  253.  
  254. }
  255.  
  256.  
  257.